package com.bstek.uflo.form.command;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.jdbc.Work;

import com.bstek.dorado.data.provider.Page;
import com.bstek.uflo.command.Command;
import com.bstek.uflo.env.Context;
import com.bstek.uflo.form.Constants;
import com.bstek.uflo.form.model.TableDefinition;
import com.bstek.uflo.form.view.common.FormState;
import com.bstek.uflo.form.view.table.dialect.Dialect;

/**
 * @author Jacky.gao
 * @since 2013年12月2日
 */
public class QueryDataCommand implements Command<Object> {
	private Page<Map<String, Object>> page;
	private TableDefinition table;
	private FormState state;
	private Map<String,Object> orders;
	private Dialect dialect;
	public QueryDataCommand(Page<Map<String, Object>> page,TableDefinition table,FormState state,Map<String,Object> orders) {
		this.page=page;
		this.table=table;
		this.state=state;
		this.orders=orders;
	}

	@SuppressWarnings("unchecked")
	public Object execute(Context context) {
		Session session = context.getSession();
		final Collection<Dialect> dialects=context.getApplicationContext().getBeansOfType(Dialect.class).values();
		session.doWork(new Work(){
			public void execute(Connection connection) throws SQLException {
				for(Dialect d:dialects){
					if(d.support(connection)){
						dialect=d;
						break;
					}
				}
			}
		});
		
		String sql="from "+table.getName()+" where 1=1 ";
		if(state!=null){
			sql+=" and "+Constants.STATE_COLUMN+"='"+state.toString()+"'";
		}
		String countSql="select count(*) "+sql;
		SQLQuery countQuery=session.createSQLQuery(countSql);
		countQuery.setResultTransformer(new MapResultTransformer());
		Map<String,Object> countResult=(Map<String,Object>)countQuery.uniqueResult();
		Object countObj=countResult.values().iterator().next();
		int count=0;
		if(countObj instanceof Integer){
			count=(Integer)countObj;
		}else if(countObj instanceof Long){
			count=((Long)countObj).intValue();
		}else{
			count=Integer.valueOf(countObj.toString());
		}
		page.setEntityCount(count);
		
		if(orders!=null && orders.size()>0){
			for(String columnName:orders.keySet()){
				sql+=" order by "+columnName+" "+orders.get(columnName)+",";
			}
			if(sql.endsWith(",")){
				sql=sql.substring(0,sql.length()-1);
			}
		}
		String querySql=dialect.getPaginationSql("select * "+sql, page.getPageNo(), page.getPageSize());
		SQLQuery query = session.createSQLQuery(querySql);
		query.setResultTransformer(new MapResultTransformer());
		List<Map<String, Object>> result=query.list();
		List<TableDefinition> slaves=table.getSlaveTables();
		if(slaves==null || slaves.size()==0){
			return result;
		}
		for(Map<String, Object> map:result){
			for(TableDefinition slave:slaves){
				String slaveSql="select * from "+slave.getName()+" where "+Constants.MASTER_ID+"="+map.get(Constants.PRIMARY_KEY_COLUMN)+"";
				SQLQuery slaveQuery = session.createSQLQuery(slaveSql);
				slaveQuery.setResultTransformer(new MapResultTransformer());
				map.put(Constants.SLAVE_PROPERTY, slaveQuery.list());
			}
		}
		page.setEntities(result);
		return null;
	}
}
